/*
 * Copyright (c) 2007 jNetX.
 * http://www.jnetx.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * jNetX. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license
 * agreement you entered into with jNetX.
 *
 * $Id$
 */
package com.jnetx.javax.sip.header;

import com.jnetx.javax.sip.util.Parametrized;

import javax.sip.header.ProxyAuthorizationHeader;
import javax.sip.header.Header;
import javax.sip.address.URI;
import java.text.ParseException;

/**
 * The Proxy-Authorization header field allows the client to identify
 * itself (or its user) to a proxy that requires authentication.  A
 * Proxy-Authorization field value consists of credentials containing
 * the authentication information of the user agent for the proxy and/or
 * realm of the resource being requested.
 * <p>
 * This header field, along with Authorization, breaks the general rules
 * about multiple header field names.  Although not a comma-separated
 * list, this header field name may be present multiple times, and MUST
 * NOT be combined into a single header line.
 * <p>
 * An UAC sends a request to a proxy server containing a Proxy-Authorization
 * header field, so that the proxy can authenticate the UAC before processing
 * the request. A proxy can challenge for credentials by rejecting a request
 * with a 407 (Proxy Authentication Required) status code upon which a UAC may
 * provide credentials for the requested resource in the Proxy-Authorization
 * header.
 * <p>
 * A Proxy-Authorization header field value applies only to the proxy
 * whose realm is identified in the "realm" parameter. When multiple proxies
 * are used in a chain, a Proxy-Authorization header field value MUST NOT be
 * consumed by any proxy whose realm does not match the "realm" parameter
 * specified in that value. Note that if an authentication scheme that does not
 * support realms is used in the Proxy-Authorization header field, a proxy
 * server MUST attempt to parse all Proxy-Authorization header field values to
 * determine whether one of them has what the proxy server considers to be
 * valid credentials.
 * <p>
 * Example:<br>
 * Proxy-Authorization: Digest username="Alice", realm="atlanta.com",
 * nonce="c60f3082ee1212b402a21831ae", response="245f23415f11432b3434341c022"
 *
 * @see javax.sip.header.Parameters
 * @see javax.sip.header.ProxyAuthenticateHeader
 * @author <a href="mailto:dparhonin@jnetx.ru">Dmitry Parhonin</a>
 * @version $Revision$
 */
public class ProxyAuthorizationHeaderImpl extends ParametrizedHeaderBase implements ProxyAuthorizationHeader {
    private final static ProxyAuthorizationHeaderParser parser = new ProxyAuthorizationHeaderParser();

    private String scheme;
    private URI uri;

    public ProxyAuthorizationHeaderImpl() {
        super(ProxyAuthorizationHeader.NAME);
    }

    ProxyAuthorizationHeaderImpl(byte[] data, int start, int end) {
        super(ProxyAuthorizationHeader.NAME, data, start, end);
    }

    @Override
    protected Parametrized<Header> createParametrized() {
        return new Parametrized<Header>(this, Parametrized.QuotationType.DOUBLE);
    }

    public Object clone() {
        final ProxyAuthorizationHeaderImpl header = new ProxyAuthorizationHeaderImpl();
        header.cloneBase(this);
        if (parsed) {
            header.cloneParameters(this);
            header.scheme = this.scheme;
            header.uri = this.uri;
        }
        return header;
    }

    protected HeaderParser getParser() {
        return parser;
    }

    protected String getValueAsString() {
        return scheme;
    }

    @Override
    protected StringBuilder getParametersAsString(StringBuilder sb, char delimiter) {
        final String params = parametrized.getParametersAsString(',');
        sb.append(' ');
        if (params != null && !params.equals("")) {
            sb.append(' ').append(params);
            if (uri != null)
                sb.append(uri.toString());
        } else
            sb.append(uri.toString());
        return sb;
    }

    /**
     * Sets the scheme of the Response information for this AuthorizationHeader.
     * For example, Digest.
     *
     * @param scheme the new string value that identifies the response
     *               information scheme.
     */
    public void setScheme(String scheme) {
        parse();
        this.scheme = scheme;
        invalidateHeaderData();
    }

    /**
     * Returns the scheme of the Response information for this AuthorizationHeader.
     *
     * @return the string value of the response information.
     */
    public String getScheme() {
        parse();
        return scheme;
    }

    /**
     * Sets the Realm of the AuthorizationHeader to the <var>realm</var>
     * parameter value. Realm strings MUST be globally unique.  It is
     * RECOMMENDED that a realm string contain a hostname or domain name.
     * Realm strings SHOULD present a human-readable identifier that can be
     * rendered to a user.
     *
     * @param realm the new Realm String of this AuthorizationHeader.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the realm.
     */
    public void setRealm(String realm) throws ParseException {
        setParameter("realm", realm);
    }

    /**
     * Returns the Realm value of this AuthorizationHeader. This convenience
     * method returns only the realm of the complete Response.
     *
     * @return the String representing the Realm information, null if value is
     *         not set.
     */
    public String getRealm() {
        return getParameter("realm");
    }

    /**
     * Sets the Username of the AuthorizationHeader to the <var>username</var>
     * parameter value.
     *
     * @param username the new Username String of this AuthorizationHeader.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the username.
     */
    public void setUsername(String username) throws ParseException {
        setParameter("username", username);
    }

    /**
     * Returns the Username value of this AuthorizationHeader. This convenience
     * method returns only the username of the complete Response.
     *
     * @return the String representing the Username information, null if value is
     *         not set.
     */
    public String getUsername() {
        return getParameter("username");
    }

    /**
     * Sets the Nonce of the AuthorizationHeader to the <var>nonce</var>
     * parameter value.
     *
     * @param nonce the new nonce String of this AuthorizationHeader.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the nonce value.
     */
    public void setNonce(String nonce) throws ParseException {
        setParameter("nonce", nonce);
    }

    /**
     * Returns the Nonce value of this AuthorizationHeader.
     *
     * @return the String representing the nonce information, null if value is
     *         not set.
     */
    public String getNonce() {
        return getParameter("nonce");
    }

    /**
     * Sets the URI of the AuthorizationHeader to the <var>uri</var>
     * parameter value.
     *
     * @param uri the new URI of this AuthorizationHeader.
     */
    public void setURI(URI uri) {
        parse();
        this.uri = uri;
        invalidateHeaderData();
    }

    /**
     * Returns the DigestURI value of this AuthorizationHeader.
     *
     * @return the URI representing the URI information, null if value is
     *         not set.
     */
    public URI getURI() {
        parse();
        return this.uri;
    }

    /**
     * Sets the Response of the AuthorizationHeader to the new <var>response</var>
     * parameter value.
     *
     * @param response - the new response String of this AuthorizationHeader.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the Response.
     */
    public void setResponse(String response) throws ParseException {
        setParameter("response", response);
    }

    /**
     * Returns the Response value of this AuthorizationHeader.
     *
     * @return the String representing the Response information.
     */
    public String getResponse() {
        return getParameter("response");
    }

    /**
     * Sets the Algorithm of the AuthorizationHeader to the new
     * <var>algorithm</var> parameter value.
     *
     * @param algorithm the new algorithm String of this AuthorizationHeader.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the algorithm value.
     */
    public void setAlgorithm(String algorithm) throws ParseException {
        setParameter("algorithm", algorithm);
    }

    /**
     * Returns the Algorithm value of this AuthorizationHeader.
     *
     * @return the String representing the Algorithm information, null if the
     *         value is not set.
     */
    public String getAlgorithm() {
        return getParameter("algorithm");
    }

    /**
     * Sets the CNonce of the AuthorizationHeader to the <var>cNonce</var>
     * parameter value.
     *
     * @param cNonce the new cNonce String of this AuthorizationHeader.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the cNonce value.
     */
    public void setCNonce(String cNonce) throws ParseException {
        setParameter("cnonce", cNonce);
    }

    /**
     * Returns the CNonce value of this AuthorizationHeader.
     *
     * @return the String representing the cNonce information, null if value is
     *         not set.
     */
    public String getCNonce() {
        return getParameter("cnonce");
    }

    /**
     * Sets the Opaque value of the AuthorizationHeader to the new
     * <var>opaque</var> parameter value.
     *
     * @param opaque the new Opaque string of this AuthorizationHeader.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the opaque value.
     */
    public void setOpaque(String opaque) throws ParseException {
        setParameter("opaque", opaque);
    }

    /**
     * Returns the Opaque value of this AuthorizationHeader.
     *
     * @return the String representing the Opaque information, null if the
     *         value is not set.
     */
    public String getOpaque() {
        return getParameter("opague");
    }

    /**
     * Sets the MessageQop value of the AuthorizationHeader to the new
     * <var>qop</var> parameter value.
     *
     * @param qop the new Qop string of this AuthorizationHeader.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the Qop value.
     */
    public void setQop(String qop) throws ParseException {
        setParameter("qop", qop);
    }

    /**
     * Returns the Qop value of this AuthorizationHeader.
     *
     * @return the string representing the Qop information, null if the
     *         value is not set.
     */
    public String getQop() {
        return getParameter("qop");
    }

    /**
     * Sets the Nonce Count of the AuthorizationHeader to the <var>nonceCount</var>
     * parameter value.
     *
     * @param nonceCount the new nonceCount integer of this AuthorizationHeader.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the nonceCount value.
     */
    public void setNonceCount(int nonceCount) throws ParseException {
        if (nonceCount == -1)
            removeParameter("nc");
        else
            setParameter("nc", Integer.toString(nonceCount), Parametrized.QuotationType.NONE);
    }

    /**
     * Returns the Nonce Count value of this AuthorizationHeader.
     *
     * @return the integer representing the nonceCount information, -1 if value is
     *         not set.
     */
    public int getNonceCount() {
        final String nc = getParameter("nc");
        if (nc == null)
            return -1;
        else
            return Integer.parseInt(nc);
    }
}
/*
 * $Log$
 */